//
// Created by tong on 9/28/24.
//

#pragma once
#include "Primitive.h"

// 压缩存储的网格插值数据
struct InterpolationStencil
{
    //网格索引偏移指示数组
    IntList indicator;
    //网格索引数据
    IntList stencil;
    //权重数据
    DoubleList weight;
};

// 网格插值类
class MeshInterpolation {
public:
    //性能检测flag
    static bool perfFlag_;
    //最大搜索半径
    static double maxRadius_;
    //线程数
    static unsigned int threadNum_;
    // 性能测试模式:插值10000次
    static bool perfTestMode_;
    //RAII构造函数
    //输入：网格1插值点，网格2插值点
    MeshInterpolation(const PointList& mesh1Points,const PointList& mesh2Points);

    MeshInterpolation(const PointList& mesh1Points,const PointList& mesh2Points,const size_t mesh1Size,const size_t mesh2Size);

    //删除缺省构造函数
    MeshInterpolation() =delete;

    // 将网格1上的数据插值到网格2上
    //输入：网格1数据，网格2数据
    void interpolateMesh1toMesh2 (const DoubleList& src,DoubleList& dest) const;
    void interpolateMesh1toMesh2 (const DoubleList& src,DoubleList& dest,const size_t destSize) const;
    

    // 将网格2上的数据插值到网格1上
    //输入：网格2数据，网格1数据
    void interpolateMesh2toMesh1 (const DoubleList& src,DoubleList& dest) const;
    void interpolateMesh2toMesh1 (const DoubleList& src,DoubleList& dest,const size_t destSize) const;

    //释放KD树内存
    void freeTree();
    void freeAll();
private:
    //网格1数据位置实体坐标
    const PointCloud mesh1PointCloud_;
    //网格2数据位置实体坐标
    const PointCloud mesh2PointCloud_;

    //网格1KD树
    unique_ptr<KDTreeL2Type> mesh1KDTreePtr_;
    //网格2KD树
    unique_ptr<KDTreeL2Type> mesh2KDTreePtr_;
    //网格1到网格2的插值数据(模板+权重)
    InterpolationStencil mesh1ToMesh2IpData_;
    //网格2到网格1的插值数据(模板+权重)
    InterpolationStencil mesh2ToMesh1IpData_;

    //检测数据大小是否合法，防止内存越界
    //输入：源数据，插值模板，目标数据
    static void checkDataSize(const DoubleList& src,const InterpolationStencil& stencil,DoubleList& dest, const size_t dest_size);
    
    //构建双向插值模板
    //输入：KD树，插值点，插值模板
    static void buildInterpolationStencil(const KDTreeL2Type& tree,const PointCloud& pointsCloud,InterpolationStencil& stencil);
    
    //网格插值
    //输入：源数据，插值模板，目标数据
    static void interpolate(const DoubleList& src,const InterpolationStencil& stencil,DoubleList& dest, const size_t dest_size);

};

// 计算误差
//输入：源数据，目标数据
DoubleList calcError(const DoubleList& srcField,const DoubleList& desField);
